package network

import (
	"encoding/binary"
	"errors"
	"io"
	"math"
)

// len data
type MsgParser struct {
	MinMsgLen uint32
	MaxMsgLen uint32
	HeaderLen int
}

func NewParser() *MsgParser {
	parser := new(MsgParser)
	parser.HeaderLen = 4
	parser.MinMsgLen = 0
	parser.MaxMsgLen = 4096

	return parser
}

func (p *MsgParser) SetMsgLen(MinMsgLen uint32, MaxMsgLen uint32) {
	if MinMsgLen != 0 {
		p.MinMsgLen = MinMsgLen
	}
	if MaxMsgLen != 0 {
		p.MaxMsgLen = MaxMsgLen
	}

	var max uint32 = math.MaxUint32
	if p.MinMsgLen > max {
		p.MinMsgLen = max
	}
	if p.MaxMsgLen > max {
		p.MaxMsgLen = max
	}
}

func (p *MsgParser) ParseData(conn *TcpConn) ([]byte, error) {
	//获取数据长度
	var datalen [4]byte
	msglenbuf := datalen[:p.HeaderLen]

	if _, err := io.ReadFull(conn, msglenbuf); err != nil { //err写在判断条件内判断语句结束则销毁
		return nil, err
	}
	msglen := binary.BigEndian.Uint32(msglenbuf)

	//log.Debug("MaxMsgLen is : %v and msglen is %v", p.MaxMsgLen, msglen)
	//判断长度是否符合要求
	if msglen > p.MaxMsgLen {
		return nil, errors.New("message is too long")
	} else if msglen < p.MinMsgLen {
		return nil, errors.New("message is too short")
	}

	//读取指定长度报文
	msgdata := make([]byte, msglen)
	if _, err := io.ReadFull(conn, msgdata); err != nil {
		return nil, err
	}

	//log.Debug("%v", string(msgdata))

	//读取成功
	return msgdata, nil
}

func (p *MsgParser) AttachHeader(conn *TcpConn, args ...[]byte) error {
	//计算报文长度
	var msglen uint32
	for i := 0; i < len(args); i++ {
		msglen += uint32(len(args[i]))
	}

	//判断报文合法
	if msglen > p.MaxMsgLen {
		return errors.New("message is too long")
	} else if msglen < p.MinMsgLen {
		return errors.New("message is too short")
	}

	msg := make([]byte, uint32(p.HeaderLen)+msglen)

	//报头填充
	binary.BigEndian.PutUint32(msg, msglen)

	//内容填充
	l := p.HeaderLen
	for i := 0; i < len(args); i++ {
		copy(msg[l:], args[i])
		l += len(args[i])
	}

	//交由连接发送
	conn.Write(msg)

	return nil
}
